package net.imagine.backend.mockrmi.remote.provider.netty.server;

import java.net.InetSocketAddress;
import java.util.concurrent.Executors;

import net.imagine.backend.mockrmi.remote.server.Server;
import net.imagine.backend.mockrmi.util.Constants;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jboss.netty.bootstrap.ServerBootstrap;
import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.ChannelPipelineFactory;
import org.jboss.netty.channel.Channels;
import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory;
import org.jboss.netty.handler.codec.serialization.ClassResolvers;
import org.jboss.netty.handler.codec.serialization.ObjectDecoder;
import org.jboss.netty.handler.codec.serialization.ObjectEncoder;

/**
 * Netty服务器，包含一个ServerBootstrap对象，用于处理客户端的请求
 * 
 * @author wuqh
 * @see ServerBootstrap
 */
public class NettyServer implements Server {
	private static final Log logger = LogFactory.getLog(NettyServer.class);
	private final int port;
	private int serviceCount;
	private ServerBootstrap bootstrap;

	private boolean startuped = false;

	public NettyServer(int port) {
		this.port = port;
	}

	public synchronized void startup() {
		// 默认为CPU核心数*2（也可改为Runtime.getRuntime().availableProcessors() + 1）
		bootstrap = new ServerBootstrap(new NioServerSocketChannelFactory(Executors.newCachedThreadPool(),
				Executors.newCachedThreadPool()));

		bootstrap.setPipelineFactory(new ChannelPipelineFactory() {

			@Override
			public ChannelPipeline getPipeline() throws Exception {
				return Channels.pipeline(
						new ObjectEncoder(Constants.OBJECT_ESTIMATE_LEN),
						new ObjectDecoder(Constants.OBJECT_MAX_LEN, ClassResolvers.weakCachingResolver(this.getClass()
								.getClassLoader())), new NettyServerIoHandler());
			}
		});

		bootstrap.setOption("receiveBufferSize", Constants.SERVER_RECEIVE_BUFFER_SIZE);
		bootstrap.setOption("sendBufferSize", Constants.SERVER_SEND_BUFFER_SIZE);
		bootstrap.setOption("keepAlive", Constants.SERVER_KEEP_ALIVE);

		bootstrap.bind(new InetSocketAddress(port));
		logger.debug("server binded to port " + port);
		this.startuped = true;
	}

	/**
	 * 关闭服务器，结束服务器线程
	 */
	public synchronized void shutdown() {
		if (bootstrap == null) {
			return;
		}
		if (this.serviceCount != 0) {
			logger.warn("there was service registed in server, but server will ignore and shutdown");
		}
		// 等待所有线程处理完后关闭
		bootstrap.releaseExternalResources();
		this.startuped = false;
	}

	public boolean isStartuped() {
		return startuped;
	}

	public synchronized int getServiceCount() {
		return serviceCount;
	}

	public synchronized void increaseServiceCount() {
		this.serviceCount++;
	}

	public synchronized void decreaseServiceCount() {
		this.serviceCount--;
	}

	// public static void main(String... args) {
	// ServiceRegistry.regist(MockRmiUtils.genId(12345, "mockService"), new
	// test.MockServiceImpl());
	// NettyServer server = new NettyServer(12345);
	// server.startup();
	// }
}
